package com.example.demo.excel.support;

/**
 * Copyright (c) 2018-2022 ThunderSoft
 * All Rights Reserved by Thunder Software Technology Co., Ltd and its affiliates.
 * You may not use, copy, distribute, modify, transmit in any form this file
 * except in compliance with ThunderSoft in writing by applicable law.
 */

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liyuncong
 * @version 1.0
 * @file CsvUtils
 * @brief CsvUtils
 * @details CSV文件工具类
 * @date 2022-11-30
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                        NAME               DESCRIPTION
 * 2022-11-30                  liyuncong          Created
 */
public class CsvUtils {
    private static final Logger logger = LoggerFactory.getLogger(CsvUtils.class);

    //行尾分隔符定义
    private final static String NEW_LINE_SEPARATOR = "\n";

    /**
     * csv表头、行数据
     */
    public static class CsvHeadValue {
        private List<String> heads;
        private List<Object> values;

        public List<String> getHeads() {
            return heads;
        }

        public void setHeads(List<String> heads) {
            this.heads = heads;
        }

        public List<Object> getValues() {
            return values;
        }

        public void setValues(List<Object> values) {
            this.values = values;
        }
    }

    /**
     * 制作csv临时文件
     *
     * @param fileName 文件名（不需要后缀）
     * @param head     表头
     * @param values   表数据
     * @return csv文件
     */
    public static File makeTempCSV(
        String filePath, String fileName,
        List<String> head, List<List<Object>> values,
        String charset
    ) {
        try {
            File file = File.createTempFile(fileName, ".csv", new File(filePath));
            CSVFormat csvFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);
            BufferedWriter bufferedWriter =
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),
                    StringUtils.isEmpty(charset) ? StandardCharsets.UTF_8.toString() : charset));
            CSVPrinter printer = new CSVPrinter(bufferedWriter, csvFormat);
            printer.printRecord(head);
            for (List<Object> value : values) {
                printer.printRecord(value);
            }
            printer.close();
            bufferedWriter.close();
            return file;
        } catch (IOException exception) {
            logger.error("make temp csv file error", exception);
            throw new RuntimeException(exception);
        }
    }

    /**
     * 解析csv文件
     *
     * @param mFile csv文件 //csv默认中文支持ANSI编码
     * @return 解析数据
     */
    public static CsvHeadValue readFileWithHeads(MultipartFile mFile) {
        BufferedReader bufferedReader = null;
        InputStreamReader inputStreamReader = null;
        InputStream temp1 = null;
        InputStream temp2 = null;
        try (ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream()) {
            arrayOutputStream.write(mFile.getBytes());
            temp1 = new ByteArrayInputStream(arrayOutputStream.toByteArray());
            temp2 = new ByteArrayInputStream(arrayOutputStream.toByteArray());
            temp1.close();
            inputStreamReader =
                new InputStreamReader(temp2, StandardCharsets.UTF_8);
            bufferedReader = new BufferedReader(inputStreamReader);
            CSVParser parser = CSVFormat.DEFAULT.parse(bufferedReader);
            final List<String> headerNames = new ArrayList<>();
            List<Object> values = new ArrayList<>();
            boolean isHead = true;
            for (CSVRecord record : parser.getRecords()) {
                Map<String, Object> value = new HashMap<>();
                for (int i = 0; i < record.size(); i++) {
                    if (isHead) {
                        headerNames.add(record.get(i));
                    } else {
                        value.put(headerNames.get(i), record.get(i));
                    }
                }
                if (!isHead) {
                    values.add(value);
                }
                isHead = false;
            }
            final CsvHeadValue headValue = new CsvHeadValue();
            headValue.setHeads(headerNames);
            headValue.setValues(values);
            return headValue;
        } catch (IOException exception) {
            logger.error("parse csv error{}", exception.getMessage(), exception);
            throw new RuntimeException(exception);
        } finally {
            try {
                //使用装饰流时，只需要关闭最后面的装饰流即可
                if (null != bufferedReader) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
